import datetime
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.views import generic
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.views.generic import View
from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy, reverse

from .forms import RenewBookForm
from .models import Book, BookInstance, Author


# 如果用户未登录，重定向到登录页面302
@login_required
# 如果用户已经登录但是没有'can_mark_returned'权限，则返回403 Forbidden错误页面
# 'app_label.permission_codename.'
@permission_required('catalog.can_mark_returned', raise_exception=True)
# 用户权限在管理后台中进行设置
def my_view(request):
    return HttpResponse("You have can_mark_returned permission")


class MyView(LoginRequiredMixin, View):
    login_url = '/accounts/login/'  # 用户未登录访问该试图对应的URL，重定向到登录页面
    redirect_field_name = 'next'  # 重定向查询参数名字，默认为'next'


def index(request):
    num_books = Book.objects.count()
    num_instances = BookInstance.objects.count()
    num_instances_available = BookInstance.objects.filter(status__exact='a').count()
    num_authors = Author.objects.count()

    # 通过会话实现查看访问次数
    num_visits = request.session.get('num_visits', 1)
    request.session['num_visits'] = num_visits + 1

    context = {
        'num_books': num_books,
        'num_instances': num_instances,
        'num_instances_available': num_instances_available,
        'num_authors': num_authors,
        'num_visits': num_visits,
    }

    return render(request, 'index.html', context)


# 书的列表页面
class BookListView(generic.ListView):
    model = Book
    context_object_name = 'book_list'
    template_name = 'catalog/book_list.html'
    paginate_by = 1  # 分页，每页显示多少条数据

    # def get_queryset(self):
    #     return Book.objects.filter(title__icontains='war')[:5]

    # 上下文数据
    def get_context_data(self, **kwargs):
        # 拿到原有的上下文
        context = super().get_context_data(**kwargs)
        # 添加新的上下文
        context['extra_data'] = 'some random data'
        return context


# 书的详情页面
class BookDetailView(generic.DetailView):
    model = Book
    # 默认的模板文件名为book_detail.html
    # 默认上下文对象的名字为book


class AuthorListView(generic.ListView):
    """Generic class-based list view for a list of authors."""
    model = Author
    paginate_by = 10


class AuthorDetailView(generic.DetailView):
    """Generic class-based detail view for an author."""
    model = Author


# mybooks/
# 显示当前登录用户所借的所有书籍
class LoadedBooksByUserListView(LoginRequiredMixin, generic.ListView):
    model = BookInstance
    template_name = 'catalog/bookinstance_list_borrowed_user.html'
    paginate_by = 10

    def get_queryset(self):
        return BookInstance.objects.filter(borrower=self.request.user).filter(status__exact='o').order_by('due_back')


# 显示所有借出去的书籍 - 只给图书管理员这个组的成员查看该页面，必须具有can_mark_returned权限
# 用户本身有can_mark_returned权限，或者他所在的组有这个权限
# 否则访问该也页面会返回403 Forbidden
# 超级管理员具有所有的权限
class LoanedBooksAllListView(PermissionRequiredMixin, generic.ListView):
    """Generic class-based view listing all books on loan. Only visible to users with can_mark_returned permission."""
    model = BookInstance
    permission_required = 'catalog.can_mark_returned'
    template_name = 'catalog/bookinstance_list_borrowed_all.html'
    paginate_by = 10

    def get_queryset(self):
        return BookInstance.objects.filter(status__exact='o').order_by('due_back')


# 表单相关的模板变量
# {{ form.renewal_date }}: The whole field.
# {{ form.renewal_date.errors }}: The list of errors.
# {{ form.renewal_date.id_for_label }}: The id of the label.
# {{ form.renewal_date.help_text }}: The field help text.
# book/<uuid:pk>/renew/
# 用户必须登录并且具有can_mark_returned权限才能访问这个页面
# 更新某个bookinstance租借时间-续订
@login_required
@permission_required('catalog.can_mark_returned', raise_exception=True)
def renew_book_librarian(request, pk):
    book_instance = get_object_or_404(BookInstance, pk=pk)

    if request.method == 'POST':
        form = RenewBookForm(request.POST)
        if form.is_valid():
            # 更新数据库中的数据
            book_instance.due_back = form.cleaned_data['renewal_date']
            book_instance.save()
            return HttpResponseRedirect(reverse('all-borrowed'))
    else:
        # The form is seeded with a date three weeks in the future.
        proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3)
        # 如果是GET请求，输入框中默认显示为三个星期后的日期
        form = RenewBookForm(initial={'renewal_date': proposed_renewal_date})
    context = {
        'form': form,
        'book_instance': book_instance
    }
    return render(request, 'catalog/book_renew_librarian.html', context)


# 'author/create/'
class AuthorCreate(CreateView):
    # 指定模型和字段 - 或者使用表达属性 form_class = AuthorForm
    model = Author
    fields = ['first_name', 'last_name', 'date_of_birth', 'date_of_death']
    initial = {'date_of_death': '11/06/2020'}


# 'author/<int:pk>/update/',
class AuthorUpdate(UpdateView):
    model = Author
    fields = '__all__'  # Not recommended (potential security issue if more fields added)


# Add support for browsers which only accept GET and POST for now.
# 浏览器只支持POST和GET请求，背后DELETE操作使用POST请求完成
# 'author/<int:pk>/delete/',
class AuthorDelete(DeleteView):
    model = Author
    success_url = reverse_lazy('authors')  # 删除记录成功后重定向到作者列表页面
